#ifndef NBT_H_
#define NBT_H_
#include <list> // used for NBTFile, TAG_Compound

class Chunk;

typedef unsigned char UBYTE;

namespace NBT
{
	class ITAG;
	class NBTFile;

	// Takes the binary buffer and decodes it to an NBT format
	NBTFile *Decode(const char *buff, unsigned int length);

	// puts the binary into a chunk object
	void DecodeIntoChunk(const char *buff, unsigned int length, Chunk* _chunk);

	// Writes an NBT file to plain ASCII
	bool WriteToText(const char*szFile, NBTFile const *file);

	// Our very very simple Named Binary Tag (NBT) file:
	class NBTFile
	{
	public:
		std::list<ITAG *> tags;

		NBTFile() { }
		~NBTFile();
	};

	// Enumeration for all the tag types (these are actually bytes codes)
	enum NBT_TAG : UBYTE { END = 0, BYTE, SHORT, INT, LONG, FLOAT, DOUBLE, 
		BYTE_ARRAY, STRING, LIST, COMPOUND };

	// The interface class for all tags
	class ITAG
	{
	public:
		NBT_TAG type;
		char *szName;

		ITAG() : szName(NULL), type(END) { }
		~ITAG();
	};
	
	// All the rest :

	#pragma region TAGs

	class TAG_End : public ITAG { };

	class TAG_Byte : public ITAG
	{
	public:
		UBYTE payload;

		TAG_Byte() : payload(0) { }
	};

	class TAG_Short : public ITAG
	{
	public:
		_int16 payload;

		TAG_Short() : payload(0) { }
	};

	class TAG_Int : public ITAG
	{
	public:
		_int32 payload;

		TAG_Int() : payload(0) { }
	};

	class TAG_Long : public ITAG
	{
	public:
		_int64 payload;

		TAG_Long() : payload(0) { }
	};

	class TAG_Float : public ITAG
	{
	public:
		float payload;

		TAG_Float() : payload(0.f) { }
	};

	class TAG_Double : public ITAG
	{
	public:
		double payload;

		TAG_Double() : payload(0.0) { }
	};

	class TAG_Byte_Array : public ITAG
	{
	public:
		_int32 length;
		UBYTE *payload;

		TAG_Byte_Array() : payload(NULL), length(0) { }
		~TAG_Byte_Array();
	};

	class TAG_String : public ITAG
	{
	public:
		_int16 length;
		char *payload;

		TAG_String() : payload(NULL), length(0) { }
		~TAG_String();
	};

	class TAG_List : public ITAG
	{
	public:
		NBT_TAG tagIds;
		_int32 length;
		ITAG **payload;

		TAG_List() : tagIds(END), payload(NULL), length(0) { }
		~TAG_List();
	};

	class TAG_Compound : public ITAG
	{
	public:
		std::list<ITAG *> payload;

		TAG_Compound() { }
		~TAG_Compound();
	};
	#pragma endregion
};

#endif